package com.example.memegenerator.service;

import com.example.memegenerator.model.Meme;
import com.example.memegenerator.model.dto.MemeDto;
import com.example.memegenerator.repository.MemeRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class MemeService {
    private final MemeRepository memeRepository;
    private final StorageService storageService;
    private final GifService gifService;

    public MemeDto createMeme(MultipartFile image, String topText, String bottomText) throws Exception {
        String imageUrl = storageService.store(image);

        Meme meme = new Meme();
        meme.setImageUrl(imageUrl);
        meme.setTopText(topText);
        meme.setBottomText(bottomText);

        Meme savedMeme = memeRepository.save(meme);
        return convertToDto(savedMeme);
    }

    public Page<MemeDto> getPopularMemes(Pageable pageable) {
        return memeRepository.findAllByOrderByShareCountDesc(pageable)
                .map(this::convertToDto);
    }

    public MemeDto incrementShareCount(Long id) {
        Meme meme = memeRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("Meme not found"));

        meme.setShareCount(meme.getShareCount() + 1);
        Meme updatedMeme = memeRepository.save(meme);
        return convertToDto(updatedMeme);
    }
    
    public byte[] generateGif(MultipartFile imageFile, String topText, String bottomText, int frames, int delay, String animationType,
                             String fontFamily, int fontSize, String fontColor, String strokeColor, int strokeWidth,
                             boolean bold, boolean italic, String textAlign, int topTextY, int bottomTextY) throws IOException {
        // 读取上传的图片
        BufferedImage originalImage = ImageIO.read(imageFile.getInputStream());
        
        // 创建帧列表
        List<BufferedImage> frameImages = new ArrayList<>();
        
        // 确保帧数至少为10，动画效果才明显
        frames = Math.max(frames, 10);
        
        // 解析颜色
        Color textColorObj = parseColor(fontColor);
        Color strokeColorObj = parseColor(strokeColor);
        
        // 计算合适的字体大小 - 如果没有指定，则根据图片宽度动态调整
        int effectiveFontSize = fontSize > 0 ? fontSize : Math.max(20, Math.min(originalImage.getWidth() / 15, 40));
        
        // 设置文本Y坐标的默认值，如果没有提供的话
        int effectiveTopTextY = topTextY > 0 ? topTextY : originalImage.getHeight() / 8 + effectiveFontSize;
        int effectiveBottomTextY = bottomTextY > 0 ? bottomTextY : originalImage.getHeight() - originalImage.getHeight() / 8;
        
        // 为每一帧生成不同效果
        for (int i = 0; i < frames; i++) {
            // 复制原始图像
            BufferedImage frame = new BufferedImage(
                    originalImage.getWidth(),
                    originalImage.getHeight(),
                    BufferedImage.TYPE_INT_RGB); // 使用RGB而不是ARGB以避免透明问题
            
            // 创建Graphics2D对象来绘制内容
            Graphics2D g2d = frame.createGraphics();
            
            // 使用更好的渲染质量
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
            
            // 绘制原始图像
            g2d.drawImage(originalImage, 0, 0, null);
            
            // 根据动画类型应用不同的文字动画效果
            applyTextAnimation(g2d, topText, bottomText, animationType, i, frames, 
                              originalImage.getWidth(), originalImage.getHeight(), 
                              fontFamily, effectiveFontSize, textColorObj, strokeColorObj, strokeWidth, 
                              bold, italic, textAlign, effectiveTopTextY, effectiveBottomTextY);
            
            g2d.dispose();
            frameImages.add(frame);
        }
        
        // 使用GifService生成GIF文件
        return gifService.createGif(frameImages, delay);
    }
    
    /**
     * 解析颜色字符串(如 #FFFFFF) 为Color对象
     */
    private Color parseColor(String colorStr) {
        if (colorStr == null || colorStr.isEmpty()) {
            return Color.WHITE;
        }
        
        try {
            return Color.decode(colorStr);
        } catch (NumberFormatException e) {
            // 如果解析失败，返回白色
            return Color.WHITE;
        }
    }
    
    /**
     * 应用不同的文字动画效果
     */
    private void applyTextAnimation(Graphics2D g2d, String topText, String bottomText, String animationType, 
                                   int frameIndex, int totalFrames, int width, int height, 
                                   String fontFamily, int fontSize, Color textColor, Color strokeColor, 
                                   int strokeWidth, boolean bold, boolean italic, String textAlign,
                                   int topTextY, int bottomTextY) {
        // 计算动画进度 (0.0 到 1.0)
        float progress = (float) frameIndex / (float) totalFrames;
        
        // 计算各种动画参数
        float angle = progress * 2 * (float) Math.PI; // 0 到 2π 的角度
        
        // 设置文字对齐方式和相应的X坐标
        int centerX = width / 2;
        int textX;
        if ("center".equals(textAlign)) {
            textX = centerX;
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        } else if ("left".equals(textAlign)) {
            textX = fontSize;
        } else { // right
            textX = width - fontSize;
        }
        
        // 设置字体为支持中文的字体
        Font originalFont = g2d.getFont();
        
        // 尝试使用指定的字体，如果不支持中文则回退到备选字体
        String[] fontNames = {fontFamily, "Microsoft YaHei", "SimSun", "SimHei", "NSimSun", "FangSong", "KaiTi", "Arial Unicode MS", 
                              "Noto Sans CJK SC", "Droid Sans Fallback", "WenQuanYi Micro Hei", "Source Han Sans CN", "Dialog"};
        
        // 创建字体样式
        int fontStyle = Font.PLAIN;
        if (bold) fontStyle |= Font.BOLD;
        if (italic) fontStyle |= Font.ITALIC;
        
        // 遍历字体列表，找到支持中文的字体
        Font chineseFont = null;
        for (String fontName : fontNames) {
            try {
                Font testFont = new Font(fontName, fontStyle, fontSize);
                if (testFont.canDisplayUpTo(topText == null ? "测试" : topText) == -1 && 
                    testFont.canDisplayUpTo(bottomText == null ? "测试" : bottomText) == -1) {
                    chineseFont = testFont;
                    break;
                }
            } catch (Exception e) {
                // 忽略找不到字体的异常，继续尝试下一个
            }
        }
        
        // 如果没有找到合适的字体，使用默认的Dialog字体
        if (chineseFont == null) {
            chineseFont = new Font("Dialog", fontStyle, fontSize);
        }
        
        g2d.setFont(chineseFont);
        g2d.setColor(textColor);
        
        // 根据不同动画类型应用不同的效果
        switch (animationType) {
            case "bounce":
                // 弹跳效果：使用正弦函数产生上下移动
                float bounceOffset = (float) Math.sin(angle * 2) * height / 20; // 增大振幅
                drawText(g2d, topText, textX, topTextY + bounceOffset, width, textAlign, strokeColor, strokeWidth);
                drawText(g2d, bottomText, textX, bottomTextY + bounceOffset, width, textAlign, strokeColor, strokeWidth);
                break;
                
            case "wave":
                // 波浪效果：每个字符有不同的垂直偏移
                if (topText != null && !topText.isEmpty()) {
                    drawWaveText(g2d, topText, textX, topTextY, angle, width, textAlign, textColor, strokeColor, strokeWidth);
                }
                if (bottomText != null && !bottomText.isEmpty()) {
                    drawWaveText(g2d, bottomText, textX, bottomTextY, angle, width, textAlign, textColor, strokeColor, strokeWidth);
                }
                break;
                
            case "shake":
                // 抖动效果：随机的小偏移
                float shakeX = (float) (Math.random() * 10 - 5); // 增大幅度
                float shakeY = (float) (Math.random() * 10 - 5);
                drawText(g2d, topText, textX + shakeX, topTextY + shakeY, width, textAlign, strokeColor, strokeWidth);
                drawText(g2d, bottomText, textX + shakeX, bottomTextY + shakeY, width, textAlign, strokeColor, strokeWidth);
                break;
                
            case "zoom":
                // 缩放效果：文字大小变化
                float scale = 1.0f + 0.3f * (float) Math.sin(angle); // 增大缩放比例
                Font scaledFont = chineseFont.deriveFont(chineseFont.getSize() * scale);
                g2d.setFont(scaledFont);
                drawText(g2d, topText, textX, topTextY, width, textAlign, strokeColor, strokeWidth);
                drawText(g2d, bottomText, textX, bottomTextY, width, textAlign, strokeColor, strokeWidth);
                g2d.setFont(chineseFont); // 恢复中文字体
                break;
                
            case "rotate":
                // 旋转效果：文字旋转
                float rotateAngle = (float) Math.sin(angle) * 25; // 增大旋转角度
                
                // 保存当前变换
                AffineTransform originalTransform = g2d.getTransform();
                
                // 对顶部文字应用旋转
                if (topText != null && !topText.isEmpty()) {
                    g2d.translate(textX, topTextY);
                    g2d.rotate(Math.toRadians(rotateAngle));
                    g2d.translate(-textX, -topTextY);
                    drawText(g2d, topText, textX, topTextY, width, textAlign, strokeColor, strokeWidth);
                    g2d.setTransform(originalTransform);
                }
                
                // 对底部文字应用旋转
                if (bottomText != null && !bottomText.isEmpty()) {
                    g2d.translate(textX, bottomTextY);
                    g2d.rotate(Math.toRadians(-rotateAngle)); // 反方向旋转
                    g2d.translate(-textX, -bottomTextY);
                    drawText(g2d, bottomText, textX, bottomTextY, width, textAlign, strokeColor, strokeWidth);
                    g2d.setTransform(originalTransform);
                }
                break;
                
            case "fade":
                // 淡入淡出效果：通过改变透明度
                float alpha = (float) Math.abs(Math.sin(angle));
                Color fadeTextColor = new Color(
                        textColor.getRed() / 255f, 
                        textColor.getGreen() / 255f, 
                        textColor.getBlue() / 255f, 
                        alpha);
                Color fadeStrokeColor = new Color(
                        strokeColor.getRed() / 255f, 
                        strokeColor.getGreen() / 255f, 
                        strokeColor.getBlue() / 255f, 
                        alpha);
                
                // 保存原始颜色
                Color originalColor = g2d.getColor();
                
                // 绘制带透明度的文本
                g2d.setColor(fadeStrokeColor);
                drawTextWithStroke(g2d, topText, textX, topTextY, width, textAlign);
                drawTextWithStroke(g2d, bottomText, textX, bottomTextY, width, textAlign);
                
                g2d.setColor(fadeTextColor);
                drawText(g2d, topText, textX, topTextY, width, textAlign, fadeStrokeColor, strokeWidth);
                drawText(g2d, bottomText, textX, bottomTextY, width, textAlign, fadeStrokeColor, strokeWidth);
                
                // 恢复原始颜色
                g2d.setColor(originalColor);
                break;
                
            default:
                // 默认简单动画：上下移动
                float defaultOffset = (float) Math.sin(angle) * 10; // 增大振幅
                drawText(g2d, topText, textX, topTextY + defaultOffset, width, textAlign, strokeColor, strokeWidth);
                drawText(g2d, bottomText, textX, bottomTextY + defaultOffset, width, textAlign, strokeColor, strokeWidth);
                break;
        }
        
        // 恢复原始字体
        g2d.setFont(originalFont);
    }
    
    /**
     * 绘制文字（带描边效果）
     */
    private void drawText(Graphics2D g2d, String text, float x, float y, int width, String textAlign, Color strokeColor, int strokeWidth) {
        if (text == null || text.isEmpty()) {
            return;
        }
        
        // 计算文本位置
        FontMetrics metrics = g2d.getFontMetrics();
        int textWidth = metrics.stringWidth(text);
        float textX = x;
        
        // 根据对齐方式调整X坐标
        if ("center".equals(textAlign)) {
            textX = x - (textWidth / 2);
        } else if ("right".equals(textAlign)) {
            textX = x - textWidth;
        }
        
        // 确保文字在图片内部
        textX = Math.max(5, Math.min(textX, width - textWidth - 5));
        
        // 绘制黑色描边
        Color originalColor = g2d.getColor();
        g2d.setColor(strokeColor);
        
        // 应用更精确的描边效果
        if (strokeWidth > 0) {
            Stroke originalStroke = g2d.getStroke();
            g2d.setStroke(new BasicStroke(strokeWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
            
            // 创建文本形状以便进行描边
            FontRenderContext frc = g2d.getFontRenderContext();
            TextLayout tl = new TextLayout(text, g2d.getFont(), frc);
            Shape shape = tl.getOutline(AffineTransform.getTranslateInstance(textX, y));
            g2d.draw(shape);
            
            g2d.setStroke(originalStroke);
        } else {
            // 简单描边
            for (int i = -1; i <= 1; i++) {
                for (int j = -1; j <= 1; j++) {
                    if (i != 0 || j != 0) {
                        g2d.drawString(text, textX + i, y + j);
                    }
                }
            }
        }
        
        // 恢复颜色并绘制主文本
        g2d.setColor(originalColor);
        g2d.drawString(text, textX, y);
    }
    
    /**
     * 绘制带轮廓的文本 - 简化版方法
     */
    private void drawTextWithStroke(Graphics2D g2d, String text, float x, float y, int width, String textAlign) {
        if (text == null || text.isEmpty()) {
            return;
        }
        
        // 计算文本位置
        FontMetrics metrics = g2d.getFontMetrics();
        int textWidth = metrics.stringWidth(text);
        float textX = x;
        
        // 根据对齐方式调整X坐标
        if ("center".equals(textAlign)) {
            textX = x - (textWidth / 2);
        } else if ("right".equals(textAlign)) {
            textX = x - textWidth;
        }
        
        // 确保文字在图片内部
        textX = Math.max(5, Math.min(textX, width - textWidth - 5));
        
        // 简化为直接描边
        g2d.drawString(text, textX, y);
    }
    
    /**
     * 绘制波浪效果的文字
     */
    private void drawWaveText(Graphics2D g2d, String text, float x, float baseY, float angle, int width, 
                              String textAlign, Color textColor, Color strokeColor, int strokeWidth) {
        if (text == null || text.isEmpty()) {
            return;
        }
        
        // 保存当前颜色和字体
        Color originalColor = g2d.getColor();
        Font originalFont = g2d.getFont();
        
        // 获取字体度量以计算文本宽度
        FontMetrics metrics = g2d.getFontMetrics();
        int totalWidth = metrics.stringWidth(text);
        float startX = x;
        
        // 根据对齐方式调整起始X坐标
        if ("center".equals(textAlign)) {
            startX = x - (totalWidth / 2);
        } else if ("right".equals(textAlign)) {
            startX = x - totalWidth;
        }
        
        // 确保文本在图像范围内
        startX = Math.max(10, Math.min(startX, width - totalWidth - 10));
        
        // 获取每个字符的渲染位置
        // 使用codePoints处理Unicode字符，包括中文等多字节字符
        final float[] positions = new float[text.length() * 2];
        float currentX = startX;
        
        for (int i = 0; i < text.length(); i++) {
            char c = text.charAt(i);
            String charStr = String.valueOf(c);
            int charWidth = metrics.stringWidth(charStr);
            
            positions[i * 2] = currentX;
            
            // 计算该字符的垂直偏移 - 增大波浪幅度
            float waveOffset = (float) Math.sin(angle + i * 0.5) * 15;
            positions[i * 2 + 1] = baseY + waveOffset;
            
            currentX += charWidth;
        }
        
        // 按字符绘制描边和主文本
        for (int i = 0; i < text.length(); i++) {
            float charX = positions[i * 2];
            float charY = positions[i * 2 + 1];
            String charStr = String.valueOf(text.charAt(i));
            
            // 使用drawText方法统一绘制带描边的文字
            g2d.setColor(textColor);
            drawText(g2d, charStr, charX, charY, width, "left", strokeColor, strokeWidth);
        }
        
        // 恢复原始设置
        g2d.setColor(originalColor);
        g2d.setFont(originalFont);
    }

    private MemeDto convertToDto(Meme meme) {
        MemeDto dto = new MemeDto();
        dto.setId(meme.getId());
        dto.setImageUrl(meme.getImageUrl());
        dto.setTopText(meme.getTopText());
        dto.setBottomText(meme.getBottomText());
        dto.setShareCount(meme.getShareCount());
        dto.setCreatedAt(meme.getCreatedAt());
        return dto;
    }

    /**
     * 生成具有多个文本元素的GIF动画
     * 
     * @param imageFile 原始图片
     * @param textElements 文本元素列表
     * @param frames 帧数
     * @param delay 延迟时间（毫秒）
     * @param animationType 动画类型
     * @return GIF动画数据
     * @throws IOException 如果处理过程中发生IO错误
     */
    public byte[] generateGifWithMultipleTexts(
            MultipartFile imageFile, 
            List<TextElement> textElements, 
            int frames, 
            int delay, 
            String animationType) throws IOException {
        
        // 读取上传的图片
        BufferedImage originalImage = ImageIO.read(imageFile.getInputStream());
        
        // 创建帧列表
        List<BufferedImage> frameImages = new ArrayList<>();
        
        // 确保帧数至少为10，动画效果才明显
        frames = Math.max(frames, 10);
        
        // 为每一帧生成不同效果
        for (int i = 0; i < frames; i++) {
            // 复制原始图像
            BufferedImage frame = new BufferedImage(
                    originalImage.getWidth(),
                    originalImage.getHeight(),
                    BufferedImage.TYPE_INT_RGB); // 使用RGB而不是ARGB以避免透明问题
            
            // 创建Graphics2D对象来绘制内容
            Graphics2D g2d = frame.createGraphics();
            
            // 使用更好的渲染质量
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
            
            // 绘制原始图像
            g2d.drawImage(originalImage, 0, 0, null);
            
            // 计算动画进度 (0.0 到 1.0)
            float progress = (float) i / (float) frames;
            
            // 计算各种动画参数
            float angle = progress * 2 * (float) Math.PI; // 0 到 2π 的角度
            
            // 绘制每个文本元素
            for (TextElement element : textElements) {
                if (element.getText() == null || element.getText().isEmpty()) continue;
                
                // 应用不同的动画效果
                applyTextAnimationToElement(g2d, element, animationType, i, frames, 
                    originalImage.getWidth(), originalImage.getHeight(), angle);
            }
            
            g2d.dispose();
            frameImages.add(frame);
        }
        
        // 使用GifService生成GIF文件
        return gifService.createGif(frameImages, delay);
    }
    
    /**
     * 对单个文本元素应用动画效果
     */
    private void applyTextAnimationToElement(Graphics2D g2d, TextElement element, String animationType, 
                                           int frameIndex, int totalFrames, int width, int height, float angle) {
        // 设置文字对齐方式和相应的X坐标
        int textX = element.getX();
        if (textX == 0) {
            // 如果X为0，则根据对齐方式计算默认X
            if ("center".equals(element.getAlign())) {
                textX = width / 2;
            } else if ("left".equals(element.getAlign())) {
                textX = element.getFontSize();
            } else if ("right".equals(element.getAlign())) {
                textX = width - element.getFontSize();
            } else {
                // 默认居中
                textX = width / 2;
            }
        }
        
        // 创建字体样式
        int fontStyle = Font.PLAIN;
        if (element.isBold()) fontStyle |= Font.BOLD;
        if (element.isItalic()) fontStyle |= Font.ITALIC;
        
        // 尝试使用指定的字体
        String[] fontNames = {element.getFontFamily(), "Microsoft YaHei", "SimSun", "SimHei", "Arial Unicode MS", "Dialog"};
        
        // 寻找支持中文的字体
        Font chineseFont = null;
        for (String fontName : fontNames) {
            try {
                Font testFont = new Font(fontName, fontStyle, element.getFontSize());
                if (testFont.canDisplayUpTo(element.getText()) == -1) {
                    chineseFont = testFont;
                    break;
                }
            } catch (Exception e) {
                // 忽略找不到字体的异常，继续尝试下一个
            }
        }
        
        // 如果没有找到合适的字体，使用默认的Dialog字体
        if (chineseFont == null) {
            chineseFont = new Font("Dialog", fontStyle, element.getFontSize());
        }
        
        g2d.setFont(chineseFont);
        g2d.setColor(parseColor(element.getFontColor()));
        
        // 当前Y坐标
        int textY = element.getY();
        
        // 如果animationType是"separate"，则使用元素自己的动画类型
        String effectiveAnimationType = "separate".equals(animationType) && element.getAnimation() != null 
                                    ? element.getAnimation() : animationType;
        
        // 根据不同动画类型应用不同的效果
        switch (effectiveAnimationType) {
            case "bounce":
                // 弹跳效果：使用正弦函数产生上下移动
                float bounceOffset = (float) Math.sin(angle * 2) * height / 20;
                drawTextWithStyle(g2d, element, textX, textY + bounceOffset);
                break;
                
            case "wave":
                // 波浪效果：每个字符有不同的垂直偏移
                drawWaveTextWithStyle(g2d, element, textX, textY, angle);
                break;
                
            case "shake":
                // 抖动效果：随机的小偏移
                float shakeX = (float) (Math.random() * 10 - 5);
                float shakeY = (float) (Math.random() * 10 - 5);
                drawTextWithStyle(g2d, element, textX + shakeX, textY + shakeY);
                break;
                
            case "zoom":
                // 缩放效果：文字大小变化
                float scale = 1.0f + 0.3f * (float) Math.sin(angle);
                Font scaledFont = chineseFont.deriveFont(chineseFont.getSize() * scale);
                g2d.setFont(scaledFont);
                drawTextWithStyle(g2d, element, textX, textY);
                g2d.setFont(chineseFont); // 恢复原字体
                break;
                
            case "rotate":
                // 旋转效果：文字旋转
                float rotateAngle = (float) Math.sin(angle) * 25;
                
                // 保存当前变换
                AffineTransform originalTransform = g2d.getTransform();
                
                // 应用旋转
                g2d.translate(textX, textY);
                g2d.rotate(Math.toRadians(rotateAngle));
                g2d.translate(-textX, -textY);
                drawTextWithStyle(g2d, element, textX, textY);
                g2d.setTransform(originalTransform);
                break;
                
            case "fade":
                // 淡入淡出效果
                float opacity = 0.3f + 0.7f * (float) Math.abs(Math.sin(angle));
                AlphaComposite alphaComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity);
                Composite originalComposite = g2d.getComposite();
                g2d.setComposite(alphaComposite);
                drawTextWithStyle(g2d, element, textX, textY);
                g2d.setComposite(originalComposite);
                break;
                
            default:
                // 无动画效果，直接绘制
                drawTextWithStyle(g2d, element, textX, textY);
                break;
        }
    }
    
    /**
     * 使用指定样式绘制文本
     */
    private void drawTextWithStyle(Graphics2D g2d, TextElement element, float x, float y) {
        // 保存原始状态
        Font originalFont = g2d.getFont();
        Color originalColor = g2d.getColor();
        
        // 设置字体对齐方式
        int originalAlign = g2d.getFontMetrics().getAscent();
        if ("center".equals(element.getAlign())) {
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        }
        
        // 绘制描边
        if (element.getStrokeWidth() > 0) {
            g2d.setColor(parseColor(element.getStrokeColor()));
            g2d.setStroke(new BasicStroke(element.getStrokeWidth()));
            
            FontRenderContext frc = g2d.getFontRenderContext();
            TextLayout tl = new TextLayout(element.getText(), g2d.getFont(), frc);
            AffineTransform transform = AffineTransform.getTranslateInstance(x, y);
            
            // 根据对齐方式调整X坐标
            if ("center".equals(element.getAlign())) {
                transform = AffineTransform.getTranslateInstance(x - tl.getBounds().getWidth() / 2, y);
            } else if ("right".equals(element.getAlign())) {
                transform = AffineTransform.getTranslateInstance(x - tl.getBounds().getWidth(), y);
            }
            
            Shape shape = tl.getOutline(transform);
            g2d.draw(shape);
        }
        
        // 设置阴影效果
        if (element.isHasShadow()) {
            g2d.setColor(parseColor(element.getShadowColor()));
            
            // 设置阴影
            float offsetX = element.getShadowOffsetX();
            float shadowOffsetY = element.getShadowOffsetY() + y;
            float blur = element.getShadowBlur();
            
            // 使用渐变实现简单的模糊效果
            for (float b = 0; b < blur; b += 0.5f) {
                float alpha = 1.0f - b / blur;
                Color shadowColor = new Color(
                        g2d.getColor().getRed() / 255f,
                        g2d.getColor().getGreen() / 255f,
                        g2d.getColor().getBlue() / 255f,
                        alpha * 0.4f);
                g2d.setColor(shadowColor);
                
                drawAlignedText(g2d, element.getText(), x + offsetX + b/2, y + shadowOffsetY + b/2, element.getAlign());
            }
        }
        
        // 绘制主文本
        g2d.setColor(parseColor(element.getFontColor()));
        drawAlignedText(g2d, element.getText(), x, y, element.getAlign());
        
        // 恢复原始状态
        g2d.setFont(originalFont);
        g2d.setColor(originalColor);
    }
    
    /**
     * 绘制带波浪效果的文本
     */
    private void drawWaveTextWithStyle(Graphics2D g2d, TextElement element, float x, float baseY, float angle) {
        String text = element.getText();
        if (text == null || text.isEmpty()) return;
        
        // 波浪效果的幅度
        float amplitude = element.getFontSize() / 3.0f;
        
        // 保存原始状态
        Font originalFont = g2d.getFont();
        Color originalColor = g2d.getColor();
        
        // 设置描边颜色
        Color strokeColor = parseColor(element.getStrokeColor());
        
        // 设置文本颜色
        Color textColor = parseColor(element.getFontColor());
        
        // 获取字体的度量信息
        FontMetrics fm = g2d.getFontMetrics();
        
        // 确定起始绘制位置，根据对齐方式调整
        float startX = x;
        if ("center".equals(element.getAlign())) {
            startX = x - fm.stringWidth(text) / 2.0f;
        } else if ("right".equals(element.getAlign())) {
            startX = x - fm.stringWidth(text);
        }
        
        // 逐个字符绘制
        for (int i = 0; i < text.length(); i++) {
            char ch = text.charAt(i);
            
            // 计算字符在波浪上的垂直位置
            float offsetY = amplitude * (float) Math.sin(angle + i * 0.5);
            
            // 获取当前字符的宽度
            int charWidth = fm.charWidth(ch);
            
            // 绘制描边
            if (element.getStrokeWidth() > 0) {
                g2d.setColor(strokeColor);
                g2d.setStroke(new BasicStroke(element.getStrokeWidth()));
                
                FontRenderContext frc = g2d.getFontRenderContext();
                TextLayout tl = new TextLayout(String.valueOf(ch), g2d.getFont(), frc);
                Shape shape = tl.getOutline(AffineTransform.getTranslateInstance(startX, baseY + offsetY));
                g2d.draw(shape);
            }
            
            // 设置阴影效果
            if (element.isHasShadow()) {
                g2d.setColor(parseColor(element.getShadowColor()));
                
                // 设置阴影
                float offsetX = element.getShadowOffsetX();
                float shadowOffsetY = element.getShadowOffsetY() + offsetY;
                float blur = element.getShadowBlur();
                
                // 使用渐变实现简单的模糊效果
                for (float b = 0; b < blur; b += 0.5f) {
                    float alpha = 1.0f - b / blur;
                    Color shadowColor = new Color(
                            g2d.getColor().getRed() / 255f,
                            g2d.getColor().getGreen() / 255f,
                            g2d.getColor().getBlue() / 255f,
                            alpha * 0.4f);
                    g2d.setColor(shadowColor);
                    
                    g2d.drawString(String.valueOf(ch), startX + offsetX + b/2, baseY + shadowOffsetY + b/2);
                }
            }
            
            // 绘制主文本
            g2d.setColor(textColor);
            g2d.drawString(String.valueOf(ch), startX, baseY + offsetY);
            
            // 更新x坐标至下一个字符
            startX += charWidth;
        }
        
        // 恢复原始状态
        g2d.setFont(originalFont);
        g2d.setColor(originalColor);
    }
    
    /**
     * 根据对齐方式绘制文本
     */
    private void drawAlignedText(Graphics2D g2d, String text, float x, float y, String align) {
        if ("center".equals(align)) {
            FontMetrics fm = g2d.getFontMetrics();
            x = x - fm.stringWidth(text) / 2.0f;
        } else if ("right".equals(align)) {
            FontMetrics fm = g2d.getFontMetrics();
            x = x - fm.stringWidth(text);
        }
        
        g2d.drawString(text, x, y);
    }
    
    /**
     * 用于多文本GIF生成的文本元素类
     */
    public static class TextElement {
        private String text;
        private int x;
        private int y;
        private String align;
        private String fontFamily;
        private int fontSize;
        private String fontColor;
        private String strokeColor;
        private int strokeWidth;
        private boolean bold;
        private boolean italic;
        private boolean hasShadow;
        private String shadowColor;
        private int shadowBlur;
        private int shadowOffsetX;
        private int shadowOffsetY;
        private String animation;
        
        // Getters and setters
        
        public String getText() { return text; }
        public void setText(String text) { this.text = text; }
        
        public int getX() { return x; }
        public void setX(int x) { this.x = x; }
        
        public int getY() { return y; }
        public void setY(int y) { this.y = y; }
        
        public String getAlign() { return align; }
        public void setAlign(String align) { this.align = align; }
        
        public String getFontFamily() { return fontFamily; }
        public void setFontFamily(String fontFamily) { this.fontFamily = fontFamily; }
        
        public int getFontSize() { return fontSize; }
        public void setFontSize(int fontSize) { this.fontSize = fontSize; }
        
        public String getFontColor() { return fontColor; }
        public void setFontColor(String fontColor) { this.fontColor = fontColor; }
        
        public String getStrokeColor() { return strokeColor; }
        public void setStrokeColor(String strokeColor) { this.strokeColor = strokeColor; }
        
        public int getStrokeWidth() { return strokeWidth; }
        public void setStrokeWidth(int strokeWidth) { this.strokeWidth = strokeWidth; }
        
        public boolean isBold() { return bold; }
        public void setBold(boolean bold) { this.bold = bold; }
        
        public boolean isItalic() { return italic; }
        public void setItalic(boolean italic) { this.italic = italic; }
        
        public boolean isHasShadow() { return hasShadow; }
        public void setHasShadow(boolean hasShadow) { this.hasShadow = hasShadow; }
        
        public String getShadowColor() { return shadowColor; }
        public void setShadowColor(String shadowColor) { this.shadowColor = shadowColor; }
        
        public int getShadowBlur() { return shadowBlur; }
        public void setShadowBlur(int shadowBlur) { this.shadowBlur = shadowBlur; }
        
        public int getShadowOffsetX() { return shadowOffsetX; }
        public void setShadowOffsetX(int shadowOffsetX) { this.shadowOffsetX = shadowOffsetX; }
        
        public int getShadowOffsetY() { return shadowOffsetY; }
        public void setShadowOffsetY(int shadowOffsetY) { this.shadowOffsetY = shadowOffsetY; }
        
        public String getAnimation() { return animation; }
        public void setAnimation(String animation) { this.animation = animation; }
    }
}